#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <assert.h>

void (*signal_SIGTERM_handler) (void *, int sig);
void *signal_SIGTERM_v;
void (*signal_SIGINT_handler) (void *, int sig);
void *signal_SIGINT_v;

static int signal_pipe[2] = { -1, -1 };
static int flag = 0;

void sigend(void *v, int sig) 
{
	printf("In signend\n");
	flag = 1;
	printf("change flag to 1\n");
}

/* Signal flag */
void signal_handler(int sig)
{
    write(signal_pipe[1], &sig, sizeof(int));

    switch(sig) {
        case SIGTERM:
            if (signal_SIGTERM_handler)
                signal_SIGTERM_handler(signal_SIGTERM_v, SIGTERM);
            break;
        case SIGINT:
            if (signal_SIGINT_handler)
                signal_SIGINT_handler(signal_SIGINT_v, SIGINT);
            break;
        default:
            break;
    }
}

/* Signal wrapper */
void *signal_set(int signo, void (*func) (void *, int), void *v)
{
    int ret;
    struct sigaction sig;
    struct sigaction osig;

    sig.sa_handler = signal_handler;
    sigemptyset(&sig.sa_mask);
    sig.sa_flags = 0;

    ret = sigaction(signo, &sig, &osig);

    switch(signo) {
        case SIGTERM:
            signal_SIGTERM_handler = func;
            signal_SIGTERM_v = v;
            break;
        case SIGINT:
            signal_SIGINT_handler = func;
            signal_SIGINT_v = v;
            break;
    }

    if (ret < 0){
        printf("signal initial error! %d ", signo);
        return (SIG_ERR);
    }else{
        return (osig.sa_handler);
    }
}

/* Handlers intialization */
void signal_handler_init(void)
{
    int n = pipe(signal_pipe);
    assert(!n);

    fcntl(signal_pipe[0], F_SETFL, O_NONBLOCK | fcntl(signal_pipe[0], F_GETFL));
    fcntl(signal_pipe[1], F_SETFL, O_NONBLOCK | fcntl(signal_pipe[1], F_GETFL));

    signal_SIGTERM_handler = NULL;
    signal_SIGINT_handler = NULL;
}

/* Signal Ignore */
void *signal_ignore(int signo)
{
    return signal_set(signo, NULL, NULL);
}

/* Initialize signal handler */
static void signal_init(void)
{
    signal_handler_init();
    signal_set(SIGTERM, sigend, NULL);
    signal_set(SIGINT, sigend, NULL);
    signal_ignore(SIGPIPE);
}

int main(void)
{
	signal_init();

	while (1) {
		printf("In busy loop\n");
		usleep(100000);
		if (flag == 1) 
			break;
	}

	printf("Out of busy loop\n");
	return 0;
}
